iT邦幫忙

2022 iThome 鐵人賽

DAY 10
0
Modern Web

angular專案開發指南系列 第 10

挑個美美的UI框架 - Nebular

  • 分享至 

  • xImage
  •  

前言

前端的專案通常會挑一個樣式框架來搭配使用,好處是,

  1. 元件樣式如表格、列表與選單等元件不需要重新打造。
  2. 介面經過專業設計外觀優美。
  3. 元件樣式風格統一。

好的 UI框架 讓你專注於商業邏輯的開發之外也能兼顧全站的風格與美觀。


挑選UI框架

Angular 專案最常搭配的是 Angular Material,除了這款框架之外,PrimengNG-ZOORONebular 也都是 Angular 專案中常見的 UI框架,專案初期通常會決定好 UI框架,其中,

  1. 整體樣式是否符合專案需求?
  2. 元件樣式的種類是否覆蓋大多數的需求?

UI框架的挑選較為主觀,好看方便用就好。

Nebular 特色

Nebular 是一個基於 Eva 設計系統規範的可定制 Angular UI 庫,具有 40 多個 UI 組件、包含4個視覺主題,讓專案能輕鬆做到多種風格變化,RWD 的樣式設計讓專案能自適應各種裝置,另有 AuthSecurity 模塊等。

What is Nebular


安裝與配置 Nebular

Day 3 我們已經用 ng-new 建立一個名為 my-app 的 Angular 專案,接下來我們示範如何安裝 Nebularmy-app 中。

Install Nebular

Nebular 支持使用 Angular Schematics 進行初始化配置

ng add @nebular/theme

p43

  1. 選擇 default 版面。
  2. 自動配置 themes.scss
  3. BrowserAnimationsModule 模組。

也可以手動安裝

npm install --save @nebular/theme @angular/cdk @angular/animations

安裝 Eva Icons pack

npm install --save eva-icons @nebular/eva-icons

配置 Nebular 模組到 Angular 專案中 src/app/app.module.ts

import { NbThemeModule } from '@nebular/theme';

...

@NgModule({
  imports: [

    ...

    BrowserModule,
    AppRoutingModule,
    BrowserAnimationsModule,

    // this will enable the default theme, you can change this by passing `{ name: 'dark' }` to enable the dark theme
    NbThemeModule.forRoot({ name: 'default' }),

    NbLayoutModule,
    NbEvaIconsModule,
  ]
})
export class AppModule {

配置 Nebular 樣式到 Angular 專案中 angular.json

"styles": [
  "node_modules/@nebular/theme/styles/prebuilt/default.css",
],

安裝配置完成。

安裝時遇到的問題

由於 Nebular 版本較舊導致新的 NodeAngular-Cli 無法正常安裝,你可能會在安裝時得到 ERESOLVE unable to resolve dependency tree 訊息,

p44

解決方法是暫時退 node 版本,使用 nvm 指定環境 node@14.15.2@angular/cli@12.0.0-next.1 安裝完成後再將環境復原即可。

版本
Node
Angular-Cli

自動產生的 styles.scss

Nebular 配置的時候會自動新增一段代碼到 styles.scss,直接砍掉就好,我們只會用到 themes.scss

@use 'themes' as *;

@use '@nebular/theme/styles/globals' as *;

@include nb-install() {
  @include nb-theme-global();
};
/* You can add global styles to this file, and also import other style files */

如果砍掉 styles.scss 整個檔案,記得去修改 angular.json 的配置,因為styles.scssAngular 建的,

"styles": [
    "node_modules/@nebular/theme/styles/prebuilt/default.css",
    "src/themes.scss",
    "src/styles.scss"
]

建立 Nebular 首頁元件

安裝好 Nebular 後,來試試看打造一個有基本頁面佈局的首頁,建立一個首頁 ng g c home

src\app\app.module.ts

// Nebular
import { NbThemeModule } from '@nebular/theme';
import { NbEvaIconsModule } from '@nebular/eva-icons';
import { NbSidebarModule, NbLayoutModule, NbButtonModule } from '@nebular/theme';

// Home
import { HomeComponent } from './home/home.component';

@NgModule({
    declarations: [AppComponent, HomeComponent],
    imports: [
        BrowserModule,
        AppRoutingModule,
        BrowserAnimationsModule,
        NbThemeModule.forRoot({ name: 'default' }),
        NbLayoutModule,
        NbSidebarModule,
        NbButtonModule,
        NbEvaIconsModule,
    ],
    providers: [],
    bootstrap: [AppComponent],
})

src\app\app-routing.module.ts

import { HomeComponent } from './home/home.component';

const routes: Routes = [
    {
        path: 'home',
        component: HomeComponent,
    },
];

src\app\app.component.ts

import { Component } from '@angular/core';

@Component({
    selector: 'app-root',
    template: `<router-outlet></router-outlet>`,
})
export class AppComponent {}

使用 app-routing.module.tsSPA 專案通常會將 app.component.ts 當作入口,
不需要 app.component.htmlapp.component.scss 直接砍掉就好。

溫馨提醒,ng serve 模式下,有修改到模組設定的時候,最好重跑一次 ng serve

src\app\home\home.component.html

<nb-layout center>
    <nb-layout-header>Awesome Company</nb-layout-header>

    <nb-layout-column>
        Hello World!
    </nb-layout-column>

    <nb-layout-footer>Contact us</nb-layout-footer>
</nb-layout>

結果畫面

p45

Nebular 元件檔案結構整理

Nebular 中的每個元件都是模組化的,使用到的時候再 import 是為了節省 APP 的整體載入時間,但是這樣會讓你的專案比較難以維護,尤其當專案較大不只有一個根模組的時候,Nebular 元件的模組可能到處都載入難以管理,所以我的專案通常會先管理起來,

建立 src\app\_define\nebular\ 資料夾,創建 nebular.module.ts

按照 Nebular 元件的分類先建立一個 定義檔,將元件分為幾個大類匯出,之後按照不同模組的使用情況引入需要的 Nebular 元件,比較懶惰的作法就全部整合起來變成 NEBULAR_ALL,打包的時候讓 Tree Shaking 把真的沒有用到的模組過濾掉,

Components Overview

引入到 Angular 模組中只要 import NEBULAR_ALL 就可以使用所有的 Nebular 元件了,按照需求也可以自訂模組需要的元件組合。

src\app\_define\nebular\nebular.module.ts

// Nebular Global Modules
import {
    NbIconModule,
    NbLayoutModule,
    NbCardModule,
    NbStepperModule,
    NbAccordionModule,
    NbListModule,
    NbFormFieldModule,
} from '@nebular/theme';

// Nebular Navigation Modules
import { NbSidebarModule, NbMenuModule, NbTabsetModule, NbActionsModule } from '@nebular/theme';

// Nebular Forms Modules
import {
    NbInputModule,
    NbButtonModule,
    NbCheckboxModule,
    NbToggleModule,
    NbRadioModule,
    NbSelectModule,
    NbAutocompleteModule,
    NbDatepickerModule,
} from '@nebular/theme';

// Nebular Modals & Overlays Modules
import {
    NbPopoverModule,
    NbContextMenuModule,
    NbDialogModule,
    NbToastrModule,
    NbTooltipModule,
    NbWindowModule,
} from '@nebular/theme';

// Nebular Extra Modules
import {
    NbSearchModule,
    NbUserModule,
    NbAlertModule,
    NbSpinnerModule,
    NbProgressBarModule,
    NbBadgeModule,
    NbChatModule,
    NbCalendarModule,
    NbCalendarRangeModule,
    NbTreeGridModule,
} from '@nebular/theme';

/**
 * Export Nebular Modules List
 * Customize modules list here for your feature module
 *
 * @export {const} NEBULAR_GLOBAL
 */
export const NEBULAR_GLOBAL = [
    NbIconModule,
    NbLayoutModule,
    NbCardModule,
    NbStepperModule,
    NbAccordionModule,
    NbListModule,
];

/**
 * nebular navigation
 *
 * @export {const} NEBULAR_NAVIGATION
 */
export const NEBULAR_NAVIGATION = [NbTabsetModule, NbActionsModule];

/**
 * nebular forms
 *
 * @export {const} NEBULAR_FORMS
 */
export const NEBULAR_FORMS = [
    NbInputModule,
    NbButtonModule,
    NbCheckboxModule,
    NbToggleModule,
    NbRadioModule,
    NbSelectModule,
    NbAutocompleteModule,
    NbDatepickerModule,
    NbFormFieldModule,
];

/**
 * nebular modals
 *
 * @export {const} NEBULAR_MODALS
 */
export const NEBULAR_MODALS = [
    NbPopoverModule,
    NbContextMenuModule,
    NbDialogModule.forChild(),
    NbTooltipModule,
    NbWindowModule.forChild(),
];

/**
 * nebular extra
 *
 * @export {const} NEBULAR_EXTRA
 */
export const NEBULAR_EXTRA = [
    NbSearchModule,
    NbUserModule,
    NbAlertModule,
    NbSpinnerModule,
    NbProgressBarModule,
    NbBadgeModule,
    NbChatModule,
    NbCalendarModule,
    NbCalendarRangeModule,
    NbTreeGridModule,
];

/**
 * Nebular Modules for Root
 *
 * @export {const} NEBULAR_ROOT
 */
export const NEBULAR_ROOT = [
    NbSidebarModule.forRoot(),
    NbMenuModule.forRoot(),
    NbDialogModule.forRoot(),
    NbToastrModule.forRoot(),
    NbWindowModule.forRoot(),
    NbDatepickerModule.forRoot(),
];

/**
 * Nebular Modules for Child
 *
 * @export {const} NEBULAR_CHILD
 */
export const NEBULAR_CHILD = [NbSidebarModule, NbMenuModule, NbDialogModule, NbToastrModule, NbWindowModule];

/**
 * Nebular Modules for All
 *
 * @export {const} NEBULAR_ALL
 */
export const NEBULAR_ALL = [
    ...NEBULAR_GLOBAL,
    ...NEBULAR_NAVIGATION,
    ...NEBULAR_FORMS,
    ...NEBULAR_MODALS,
    ...NEBULAR_EXTRA,
];

定義 @define 檔案路徑為 src/app/_define/*

tsconfig.json

{
"compilerOptions": {
    "baseUrl": "./",
    "paths": {
        "@define/*": [
            "src/app/_define/*"
        ]
    },
    ...
}

使用 NEBULAR_ALLsrc\app\app.module.ts

import { NEBULAR_ROOT, NEBULAR_ALL } from '@define/nebular/nebular.module';

@NgModule({
    imports: [
        ...NEBULAR_ROOT,
        ...NEBULAR_ALL,
    ]
})

這樣根模組就能使用所有的 Nebular 元件了。

使用 NEBULAR_ALL 後就不需要再像官網的教學範例每次都要回到根模組再 import 一次了。


重新構建 Nebular 首頁元件

src\app\app.module.ts

// Nebular
import { NbThemeModule } from '@nebular/theme';
import { NbEvaIconsModule } from '@nebular/eva-icons';
import { NEBULAR_ROOT, NEBULAR_ALL } from '@define/nebular/nebular.module';

// Home
import { HomeComponent } from './home/home.component';

@NgModule({
    declarations: [AppComponent, HomeComponent],
    imports: [
        BrowserModule,
        AppRoutingModule,
        BrowserAnimationsModule,
        NbThemeModule.forRoot({ name: 'default' }),
        NbEvaIconsModule,
        ...NEBULAR_ROOT,
        ...NEBULAR_ALL,
    ],
    providers: [],
    bootstrap: [AppComponent],
})

載入的元件越多就越能看到這個寫法的簡潔性。

順便換個新佈局 src\app\home\home.component.html

<nb-layout>
    <nb-layout-header fixed>
        <a href="#" (click)="toggle()"><i class="nb-menu"></i></a>
    </nb-layout-header>

    <nb-layout-header subheader>
        <nb-actions>
            <nb-action icon="home-outline"></nb-action>
            <nb-action icon="search-outline"></nb-action>
            <nb-action icon="edit-outline"></nb-action>
        </nb-actions>
    </nb-layout-header>

    <nb-sidebar></nb-sidebar>

    <nb-layout-column class="colored-column-basic">Layout Content</nb-layout-column>
</nb-layout>

src\app\home\home.component.ts

import { Component } from '@angular/core';
import { NbSidebarService } from '@nebular/theme';

@Component({
    selector: 'app-home',
    templateUrl: './home.component.html',
    styleUrls: ['./home.component.scss'],
})
export class HomeComponent {
    constructor(private sidebarService: NbSidebarService) {}

    toggle() {
        this.sidebarService.toggle(true);
        return false;
    }
}

新佈局頁面
p46

為了驗證可以使用所有的元件不需在額外引入,在 Home 頁面中引入 Card

<nb-layout>
    <nb-layout-header fixed>
        <a href="#" (click)="toggle()"><i class="nb-menu"></i></a>
    </nb-layout-header>

    <nb-layout-header subheader>
        <nb-actions>
            <nb-action icon="home-outline"></nb-action>
            <nb-action icon="search-outline"></nb-action>
            <nb-action icon="edit-outline"></nb-action>
        </nb-actions>
    </nb-layout-header>

    <nb-sidebar></nb-sidebar>

    <nb-layout-column class="colored-column-basic">
    
        <!-- 在這裡加入 卡片 -->
        <nb-card status="success">
            <nb-card-header>Nebula</nb-card-header>
            <nb-card-body>
                A nebula is an interstellar cloud of dust, hydrogen, helium and other ionized gases. Originally, nebula
                was a name for any diffuse astronomical object, including galaxies beyond the Milky Way.
            </nb-card-body>
            <nb-card-footer>By Wikipedia</nb-card-footer>
        </nb-card>

        <nb-card status="danger">
            <nb-card-header>Nebula</nb-card-header>
            <nb-card-body>
                A nebula is an interstellar cloud of dust, hydrogen, helium and other ionized gases. Originally, nebula
                was a name for any diffuse astronomical object, including galaxies beyond the Milky Way.
            </nb-card-body>
            <nb-card-footer>By Wikipedia</nb-card-footer>
        </nb-card>
        <!-- 在這裡加入 卡片 結尾 -->
        
    </nb-layout-column>
</nb-layout>

新佈局頁面加入卡片元件

p47

Nebular 的元件都必須放在 <nb-layout></nb-layout> 中。


結論

Angular 使用 UI框架 主要目的是為了專案的風格統一,開發者只要花點時間熟悉這些元件的使用,就可以快速構建一個很有設計感的網站,Nebular 還包含許多的特色功能模組,有機會再來介紹這些功能。

Angular 加上有設計感的 Nebular,接下來我們從簡單的需求練習使用 Angular 來進行專案開發。

參考

Tree Shaking

值得推薦的 7 個 Angular 前端元件庫


上一篇
程式碼註解工具 - Compodoc
下一篇
讓前後端獨立開發的假資料系統 - Json Server
系列文
angular專案開發指南30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言